home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / utility / wshell12.zip / WINSHELL.TXT < prev    next >
Text File  |  1991-12-12  |  40KB  |  733 lines

  1.  
  2.  
  3.  
  4. WINDOWS SHELL
  5. FOR MICROSOFT WINDOWS 3.0
  6.  
  7.  
  8.  
  9.  
  10. by
  11.  
  12.  
  13.  
  14.  
  15. Greg McCain
  16.  
  17. December 5, 1991
  18.  
  19.  
  20.  
  21.  
  22.  
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29. Advisor: Charles Dana
  30. Computer Science Department
  31. School of Engineering
  32. California Polytechnic State University
  33. 199
  34.  
  35.  
  36. TABLE OF CONTENTS
  37.  
  38.  
  39. ABSTRACT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    iii
  40.  
  41. HOW THIS DOCUMENT IS ORGANIZED . . . . . . . . . .. . . . .    iv
  42.  
  43. LIST OF FIGURES . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .     v
  44.  
  45. Section
  46.  
  47.     I.    Features of Windows Shell . . . . . . . . . . . . . . . . . . . . . . . .     1
  48.  
  49.         Command Line . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    2
  50.  
  51.         Aliasing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    3
  52.  
  53.         Environment Variables . . . . . . . . . . . . . . . . . . . . . . . . . . .     3
  54.  
  55.         Action Bar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    3
  56.  
  57.         External Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . .     4
  58.  
  59.         Shell Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .     5
  60.  
  61.     II.    Design of Windows Shell . . . . . . . . . . . . . . . . . . . . . . . . .     7
  62.  
  63.         Graphical Objects in the Windows Shell . . . . . . . . . . . . .     7
  64.  
  65.              The WSTDIO Window . . . . .  . . . . . . . . . . . . . . .     8
  66.                 
  67.                 Pertinent Data . . . . . . . . . . . . . . . . . . . . . .    8
  68.  
  69.                 Painting The Display . . . . . . . . . . . . . . . . .    10
  70.  
  71.                 Obtaining Standard I/O input . . . . . . . . . .    11
  72.  
  73.                 Marking Text  . . . . . . . . . . . . . . . . . . . .    12
  74.  
  75.                 Command History . . . . . . . . . . . . . . . . . .    13
  76.  
  77.                 Message Directory . . . . . . . . . . . . . . . . .    13
  78.  
  79.             The ACTNBAR Window . . . . . . . . . . . . . . . . . .    14
  80.  
  81.             The WINSHELL Window . . . . . . . . . . . . . . . . .    15
  82.  
  83.         Logical Modules For Command Interpretation. . . . . . . .    16
  84.  
  85.             The Command Prompt Path . . . . . . . . . . . . . . . .    17
  86.  
  87.             The Action Button Path . . . . . . . . . . . . . . . . . . .     18
  88.  
  89.             The ALIAS.C Module . . . . . . . . . . . . . . . . . . . .    19
  90.  
  91.             The INTERP.C Module . . . . . . . . . . . . . . . . . . .    19
  92.  
  93.     III.     The Development Process . . .  . . . . . . . . . . . . . . . . . .    21
  94.  
  95. Appendix
  96.  
  97.     A. Appendix A: External Commands DLL Interface . . . . . . . . .     23
  98.  
  99.  
  100. ABSTRACT
  101.  
  102. This document discusses the purpose, features, and design of a command line 
  103. shell for Microsoft Windows 3.0, the Windows Shell.  The Windows Shell allows 
  104. users to launch both DOS and Windows programs from a command line environment, 
  105. as well as perform disk maintenance operations such as copy, deleting, and moving 
  106. files.
  107. The Windows Shell is implemented in the Microsoft Windows 3.0 environment.  
  108. The shell has been tested on systems running Windows in VGA and EGA video 
  109. modes.  The Windows Shell uses Windows 3.0 non-preemptive multitasking 
  110. techniques to allow multiple instances of the Windows Shell to run concurrently, as 
  111. well as other programs in the Windows environment.
  112. The Windows Shell introduces several new features to the typical command shell 
  113. environment, including interactive editing of Aliases and Environment variables,  an 
  114. "Action Bar" to quickly execute a command, the ability to set "permanent" options in 
  115. shell commands, and customizable fonts and screen colors.
  116. The purpose of the Windows Shell is to fill a gap in the Windows 3.0 
  117. environment.  The original environment provides a highly graphical user interface for 
  118. executing programs and file management.  While this is great for naive users, the 
  119. graphical interface can become cumbersome to experienced users.  The Windows 
  120. Shell is intended for experienced users, providing quick manipulation of files and 
  121. directories, as well as executing Windows and DOS programs.  The Windows Shell 
  122. also includes some extra graphical niceties that are discussed in the following 
  123. section.  
  124.  
  125.  
  126. HOW THIS DOCUMENT IS ORGANIZED
  127.  
  128. This document is divided into three main sections.  The first presents the 
  129. Windows Shell as seen by the user.  It discusses the feature of Windows Shell, how 
  130. to access them, and what they can do for a user.  The second section presents the 
  131. Windows Shell as seen by the programmer.  This includes a discussion of the 
  132. graphical objects seen in the Window Shell, as well as a discussion of how the 
  133. command interpretation works.  The last section discusses the development process 
  134. of the Windows Shell.  It describes the problems encountered in both design and 
  135. implementation of the Windows Shell, and any other noteworthy considerations that 
  136. were involved in the development process.
  137. The document also provides the specifications of the DLL External Commands 
  138. interface in Appendix A.  The interface is a major consideration when developing 
  139. external commands for use with the Windows Shell.
  140.  
  141.  
  142. LIST OF FIGURES
  143.  
  144. FIGURE 
  145.     1 The Command Line. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .    1
  146.     2 The Alias Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .       2
  147.     3 The Environment Editor . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .      3
  148.     4 Action Button Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . .     4
  149.     5 External Commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .      5
  150.     6 Graphical Object Design . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .     7
  151.     7 Command Interpretation Paths . . . . . . . . . . . . . . . . . . . . . . . . .    16
  152.  
  153.  
  154. I. FEATURES OF WINDOWS SHELL
  155.  
  156.  
  157. I.A. THE COMMAND LINE
  158.  
  159. figure 1
  160. The Windows Shell provides a command line interface to the windows environment.  
  161. The command line is similar in appearance to a DOS shell, with the following 
  162. exceptions:
  163. - The Windows Shell prompt allows for text marking, cutting, and pasting.
  164. - The Windows Shell offers the "Action Bar" seen on the left side of the shell 
  165. (see figure 1.)
  166. - The Windows Shell allows the user to configure the color and font used by 
  167. each instance of the shell.
  168. - The Windows Shell recognizes the '&' character to run a windows program 
  169. minimized.
  170. - The Windows Shell expands partial file names entered on the command line 
  171. into the entire file name by pressing the tab key.  If more than one file 
  172. matches the partial name, the user will be given a choice of files.
  173.  
  174.  
  175. I.B. ALIASES
  176. Windows Shell allows the user to define aliases.  Aliases allow long or complex 
  177. commands to be abbreviated for quick access.  
  178.  
  179.  
  180. figure 2
  181. Windows shell provides the Alias Editor  (as seen above in figure 2) for quick 
  182. viewing and editing of aliases.
  183.  
  184. I.C. ENVIRONMENT VARIABLES
  185.  
  186. The Windows 3.0 environment provides environment variables similar to that of DOS 
  187. and UNIX.  Unfortunately, the environment variables in the Windows Shell are not 
  188. inherited by the programs it executes.  Each new program gets a copy of the 
  189. environment that was recorded when windows was started.  However,  the 
  190. environment variables do effect the shell itself, which is useful for changing the path 
  191. or prompt.  
  192.  
  193.  
  194. figure 3
  195. Windows Shell provides the Environment Editor (as seen above in figure 3) for 
  196. quick viewing and editing of environment variables.
  197.  
  198. I.D. ACTION BAR
  199. The action bar is a column of eight buttons along the left side of the shell (see 
  200. figure 1)  It allows users to execute a predefined command at the press of a button.  
  201. The following window is used to configure the action bar:
  202.  
  203.  
  204. figure 4
  205. The Button Configuration Window allows the users to define the text seen on the 
  206. buttons and the command that is carries out.  The user can access text marked on 
  207. the Windows Shell using the '=' character.  The '=' character is replaced by a string 
  208. containing the marked text when the command is executed.  This makes it easy for a 
  209. user to mark a block of text and perform actions upon it, such as deleting or editing 
  210. files.  For example, to have a button which will delete any marked files, use the 
  211. string:
  212. del =
  213. in a "button command" box, as seen in figure 4.
  214.  
  215. I.E. EXTERNAL COMMANDS
  216. Most shells provide shell commands which are built into the shell itself.  The 
  217. Windows Shell provides only the most basic shell commands, including: change 
  218. directory (cd), make directory (md), and remove directory (rd).  The rest of the usual 
  219. shell commands are implemented as "external commands".
  220. Each external command is a Windows 3.0 Dynamic Link Library (DLL).  The 
  221. Windows Shell uses a Windows 3.0 DLL loading function to load and run external 
  222. commands.  Each external command must provide a set of functions to execute the 
  223. command, show an about box, and show an options box.
  224. The windows shell provides the "external commands window" to view and 
  225. configure external commands (see figure 5).
  226.  
  227.  
  228. figure 5
  229.  
  230. The options box allows the user to set "permanent" options on a command that will 
  231. be invoked each time the command is run.  The about box allows the user to view an 
  232. about box for the command which could contain useful information on what the 
  233. command does and how to use it.
  234. The reason the "external commands" are implemented as DLL's is that it allows new 
  235. commands to be written without modification to the shell.  Also,  the format of the DLL 
  236. is such that a normal DOS shell program can easily be ported to run under the shell.
  237.  
  238. I.6. SHELL COMMANDS
  239. The user accessible commands contained in Winshell, or Shell Commands, are 
  240. as follows:
  241. cd <dirname>     : Changes current directory to directory specified in dirname.
  242. md <dirname>     : Creates a directory as specified in dirname.
  243. rd <dirname>     : Deletes a directory as specified in dirname.
  244. <DRIVE> :    : Changes current disk specified to drive specified in DRIVE.
  245. ps    : Lists currently running processes.
  246. min <task_name>: Minimizes program with caption matching task_name.
  247. max <task_name>: Maximizes program with caption matching task_name.
  248. kill <task_name>: Closes program with caption matching task_name.
  249. exit        : Exits current Windows Shell.
  250. exitwin        : Exits Windows.
  251.  
  252.  
  253.  
  254. II. DESIGN OF WINDOWS SHELL
  255. The design of Windows Shell has been broken down into the many separate 
  256. modules, both graphical and logical.  To simplify the explanation of the design, this 
  257. section is divided into two main parts.  The first part will discuss the graphical object 
  258. design of windows shell.  That is, how the individual windows and buttons are 
  259. designed, how they function, and they the communicate with one another.  The 
  260. second part of this section will discuss the modules used in command interpretation.  
  261. This section will involve a detailed trace of the flow of control for the interpretation of 
  262. a command.
  263.  
  264. II.A. GRAPHICAL OBJECTS OF THE WINDOWS SHELL
  265. The windows shell has been divided into three main graphical objects, as seen in 
  266. figure 6.  Each of the objects is implemented in a separate C source file, and 
  267. communicate with each other via Windows messages.  Although the "Main" window 
  268. as seen in figure 6 is at the top of the hierarchy, controlling the other two windows, 
  269. this explanation will be more clear of it starts from the bottom.
  270.  
  271.  
  272. figure 6
  273. II.A.1 The WSTDIO Window
  274. By far the most important window in the shell is the WStdio window.  It is 
  275. responsible for supplying the primitives such as reading and writing characters to a 
  276. standard I/O type device.  To do this in a windowing environment, is requires 
  277. creating a "virtual" standard I/O display.  This display is represented by a data 
  278. structure, who's main element is an array of characters which represent the 
  279. characters displayed on the screen.  When characters are written to the WStdio 
  280. window, they a first copied into this character array, and then are actually displayed 
  281. on the screen.
  282. II.A.1.a Pertinent Data
  283. To better understand the implementation of the WStdio window, let's look at the 
  284. elements of the Display data structure as defined by the WStdio window.  The first 
  285. feature is the array of characters representing the display (This is referred to as the 
  286. "LineBuf".)  Second, are a set of elements used to track the state of the display:
  287.  
  288. int  iTopLine;            // Index of the current top line in the LineBuf
  289. int  iBottomLine;            // Index of the current bottom line in the
  290.                     // LineBuf
  291. int  TotalLineCount;        // the current number of line in the LineBuf
  292. int  CurCharOffset;        // offset into LineBuff of current position
  293.  
  294. These first four elements are what control current state of LineBuff itself.  LineBuff is 
  295. an array of characters, which is logically divided into fixed length lines.  The actual 
  296. number of lines available in LineBuff is a constant at compile time, but is typically 
  297. much larger than the number of lines that will currently fit in the window on screen.  
  298. (This surpluss of lines in memory is used as a scrollback buffer, as will be 
  299. discussed later.)  The indices to the top and bottom lines are used because LineBuff 
  300. is a circular buffer.  These indices always point to the portion of the LineBuff that is 
  301. currently displayed on the screen.  The TotalLineCount variable is the absolute 
  302. number of lines in LineBuff.  CurCharOffset is absolute position in LineBuff at which 
  303. the next character to be displayed will be written.
  304. The next set of elements is used when actually outputting lines to the screen.  
  305. Their uses and intentions are explained in the comments.
  306.  
  307. int  nLinesOnScreen;          // the number of lines fitting on the window
  308.                     // in it's current size
  309. int  nCurLineOnScreen;        // the current line the cursor is on in window
  310.                                    // starting from 1 (NOT 0!)
  311. int  yChar,                       // height in pixels of a line
  312. int  xCursorPos;                  // distance (in pixels) from the left hand
  313.                                    // side of the screen that the cursor is at
  314. When the user activates the scrollback feature by using the vertical scrollbar or 
  315. the PAGE UP/PAGE DOWN keys, these variables are initialized and used to track the 
  316. positioning of the scrollback:
  317.  
  318. BOOL     isScrolling;        // True is window is in a scrolling back state
  319. int      TopScrollLineNum,    // index of the top line in the LineBuff  
  320.                     // during a scrollback
  321. Another noteworthy element in the Display data structure is used to expedite the 
  322. actual outputting of lines on the screen.
  323.  
  324. int  nUnpurgedLines,              // # of line waiting to be written to
  325.                         // the screen
  326. The WStdio window does not display a line of text immediately when it is 
  327. received.  If possible, the window will wait until a predefined constant number of 
  328. lines come in before it actually displays the lines.  This can dramatically increase 
  329. the rate at which lines are displayed on the screen.  The nUnpurgedLines variable 
  330. counts the number of lines waiting to be displayed.
  331. Finally, there are elements used to track how the user has highlighted any text in 
  332. the WStdio window:
  333.  
  334. WORD wSelectState;
  335. RECT rectInversion;
  336. The wSelectState variable can be in three states: one indicating there is no 
  337. highlighted rectangle, when all bits are turned off.  The second, SS_SELECTING,  
  338. indicates the user is currently marking a rectangle. The third, SS_RECTSELECTED, 
  339. indicates that a rectangle is currently highlighted.  When in third state, the 
  340. rectInversion variable will hold the coordinates of the highlighted rectangle.
  341. II.A.1.b Painting The Display
  342. When a message is sent to the WStdio window to write a line to the display, it's first 
  343. job is to copy that line to the line buffer.  It then invalidates the region of the window 
  344. that will be effected by the new text.  Having done this, the function is essentially 
  345. done.  The job of actually writing the text to the screen comes later, in response to a 
  346. Windows WM_PAINT message.  To understand why it is implemented this way, one 
  347. must understand the concept of the MS Windows WM_PAINT message. Windows 
  348. dictates that all screen I/O should be done in response to a WM_PAINT message. 
  349. The message informs a window that it needs to repaint a portion of it's client area, 
  350. and supplies the window with the coordinates of a rectangle it needs to repaint.  Thus 
  351. upon receiving this message, the WStdio window calculates what lines need to be 
  352. painted, and paints them.  Back when a client module requested the WStdio window 
  353. to display a line, the WStdio window only had to copy the line into it's internal 
  354. Linebuff, and invalidate the portion of the window that will be effected by the new line.  
  355. By invalidating a portion of the window, Windows will generate a WM_PAINT 
  356. message, and the window will be repainted, reflecting the new line to be displayed.
  357. II.A.1.c Obtaining Standard I/O Input
  358. Perhaps the most interesting feature in the implementation of the WStdio window 
  359. is how it obtains input from the user.  To provide a function like getstr(), which does 
  360. not return until the user presses the ENTER key, the Windows message loop had to 
  361. be placed inside the getstr() command.  This allows other processes to run while the 
  362. WStdio window is waiting for input.
  363. When a client module sends a DM_GETS message to get a string from the 
  364. WStdio window, the WStdio window calls the DisplayGetStr() function.  This function 
  365. first positions the caret at the appropriate position, and then falls into a message 
  366. loop.  Inside this message loop, the function monitors the incoming messages 
  367. looking for the ENTER key to be pressed, in which case it will fall out of the loop and 
  368. return the text that was entered.  The function also monitors the incoming messages 
  369. for keys like the arrow keys, in which case it will invoke the command history, and for 
  370. WM_CLOSE message.  If a WM_CLOSE message comes in, the DisplayGetStr 
  371. function exits the message loop and returns a value indicating that the function 
  372. failed.
  373. With this method of implementing the message loop in the input function, the 
  374. client modules need not use a message loop.  The main module, WINSHELL.C, in 
  375. fact does not use a message loop.  Instead, it falls into a loop that might be expected 
  376. out of a UNIX type command, in which it displays a command prompt, gets an input 
  377. string, interprets it, and executes the appropriate action.  It does not use a message 
  378. loop at all, like most other Windows WinMain functions have to do.  But this is an 
  379. aside and will be cover more in the section on the WINSHELL.C module.
  380. In order to obtain input from the user, the WStdio window uses a Windows edit 
  381. control.  When the user sees a prompt at which he or she can type, that prompt is 
  382. actually inside a separate edit control, and not in the WStdio window itself.  The edit 
  383. control is always positioned at the end of the last character entered, much as a caret 
  384. would be.  This way, however, leaves much of the work of obtaining key-presses and 
  385. displaying characters to the edit control.  It also helps provide the standard controls 
  386. a user might expect from an input prompt.  Such things as marking text and replacing 
  387. text will remain consistent with other edit controls, and in future versions of 
  388. Windows.
  389. II.A.1.d Marking Text With The Mouse
  390. The job of marking text on the display is quite simple.  The WStdio window 
  391. responds to a WM_LBUTTONDOWN message (indicating the left mouse button is 
  392. being pressed,) by obtaining a mouse capture.  This forces Windows to send all 
  393. subsequent mouse message to the window obtaining the capture.  While in this 
  394. state, the WStdio window then responds to all WM_MOUSEMOVE messages by 
  395. inverting a rectangle between the position where the mouse was originally pressed 
  396. and the current position.  When the left mouse button is released, the capture is also 
  397. released, and the rectangle is left highlighted.
  398. The portion of highlighted text can now be accessed by both the WStdio window 
  399. itself, and by client windows via a DM_GETMARKEDTEXT message.  The function 
  400. GetMarkedText(), in the wstdio.c module,  is responsible for determining what 
  401. characters are actually marked and copying them to a buffer.  This is no simple task 
  402. when proportionally spaced fonts are in use.  The function must navigate LineBuff 
  403. and determine the actual length in pixels of each character in the buffer.  It then 
  404. compares this to coordinates that are marked in the screen, and can determine what 
  405. characters are actually marked.
  406. II.A.1.e Command History
  407. The WStdio is also responsible for providing a command history.  Whenever the 
  408. user enters a command at the command prompt, the WStdio window records the 
  409. command entered with the CommandHistory() function.  This function manages a 
  410. simple queue of a constant size.  When a user enters a command, it is added at the 
  411. end of the queue, and the first item in the queue is discarded if there are more than 
  412. the constant limit of items in the queue.  When the user presses the up and down 
  413. arrow keys, the WStdio window responds by displaying items from this queue on the 
  414. command line.
  415. II.A.1.f Wstdio Message Directory
  416. The following is a list of messages that the WStdio window provides for client 
  417. modules:
  418.  
  419.     DM_PUTS     - Writes a string to the display.
  420.  
  421.     DM_GETS    - Gets a string from the display.
  422.  
  423.     DM_CLEAR    - Clears the Wstdio window.
  424.  
  425.     DM_SETFONT    - Sets the font the Wstdio window will use.
  426.  
  427. DM_GETNUMCOLUMNS    - Returns the approximate number of columns 
  428. on the display. A column is space enough for 
  429. about 12 of the widest characters in the current 
  430. font, and a trailing tab.  This feature essentially 
  431. indicates the number of file names that can be 
  432. displayed on one line.
  433.  
  434. DM_GETMARKEDTEXT    - Returns a global handle to memory block 
  435. containing marked text.  This memory must be 
  436. freed by the user
  437.  
  438. DM_SETMORE    - Turns the more feature on and off.    When this feature 
  439. is turned on, the WStdio will automatically display a ----
  440. more---- at the bottom of the screen after the last 
  441. number of lines displayed has filled up the screen.  
  442. The more feature is automatically turned off when after 
  443. DM_GETS message is sent.
  444.  
  445. II.A.2 The ACTNBAR Window
  446. The actnbar window provides the column of user configurable push buttons along 
  447. the left hand side of the Windows Shell.  The ACTNBAR window is actually a 
  448. rectangular window surrounding the set of push buttons.  Associated with each push 
  449. button is a caption and a command.  The caption is the text that is displayed in the 
  450. button on the screen.  The command is the command string which will be invoked 
  451. when the button is pressed.
  452. When the ACTNBAR window is created, it creates it's push button children and 
  453. initializes them to defaults saved in the WINSHELL.INI configuration file.  It's job 
  454. thereafter is to report to it's parent window whenever one of it's buttons has been 
  455. pushed, passing the parent window the command string to be executed.  
  456. This is accomplished using the standard Windows WM_COMMAND message.  
  457. This message is sent to the ACTNBAR window whenever one of it's children is 
  458. pressed.  The ACTNBAR window then sends this same message to the parent, and 
  459. indicates what function to perform by setting it's own caption text the command text 
  460. assocaiated with the button.  Thus when the parent receives the WM_COMMAND 
  461. from the ACTNBAR window, it reads caption text of the ACTNBAR window, and 
  462. executes the command contained therein.
  463. Note that this logical command path is different from that of the other command 
  464. interpretation path.  A command executed in response to the ACTNBAR being 
  465. pressed is interpreted and executed in response to the WM_COMMAND message, 
  466. and is not obtained via the command interpretation loop in the WinMain function.  
  467. This is discussed more in section II.B.2.
  468. Also contained inside the ACTNBAR.C module is action button configuration 
  469. dialog box.  This allows users to configure both the caption and command of each 
  470. action button.
  471.  
  472. II.A.3 The WINSHELL Window
  473. This window is the main window of the application, and controls the other 
  474. windows as seen in figure 6.  The graphical job of this window is quite simple.  It's 
  475. job is to manage that size and position of the other two windows, namely the 
  476. WSTDIO window and the ACTNBAR window.  These windows are both children of the 
  477. WINSHELL window, and reside inside the client are of the WINSHELL window.  
  478. Apart from this, the WINSHELL also provides the menu bar as seen at the top of 
  479. the window.  It must respond to menu messages and execute the appropriate 
  480. functions.  These functions include changing the font in the WSTDIO window, 
  481. changing the colors of the Windows Shell, and popping up the various configuration 
  482. dialog boxes.  These duties mostly involve sending a single message to the 
  483. appropriate window to perform the task.  In this way, the WINSHELL window serves 
  484. more as a message router for it's children than anything else.
  485. However, if this seems to simple, that because it is.  This is only a discussion of 
  486. the graphically oriented tasks the WINSHELL window must perform.  It's main task, 
  487. that of command interpretation, is discussed in the next section.
  488. II.B LOGICAL MODULES FOR COMMAND INTERPRETATION
  489. This section discusses the modules involved in command interpretation.  Now 
  490. that the relationship of the 3 main windows has been defined, the matter of 
  491. understanding command interpretation will be much easier.  First let's look at the 
  492. design of the command interpreter, as seen in figure 7.
  493.  
  494.  
  495. figure 7
  496.  
  497. The flow of control in figure 7 moves left to right.  The diamond shaped modules 
  498. indicate modules which are returning user input.  The circular modules perform some 
  499. logical operation on the input data, and the square boxes will be the end result of the 
  500. command.
  501. There exist two paths in which a command can be executed by the shell.  The 
  502. first is by the user entering a command at the command prompt.  The second, is the 
  503. user pressing an action button.  The former is accomplished by looping for user 
  504. input, interpreting it, and executing it; the latter is done only in response to a user 
  505. pressing an action button.
  506. II.B.1 The Command Prompt Path
  507. Command interpretation begins in the WINSHELL.C module.  This module 
  508. contains the WinMain function, which is the entry point of a Windows application.  
  509. After performing it's initializations and creating it's child windows, the WINSHELL.C 
  510. module falls into the command interpretation loop as follows:
  511. do
  512. {
  513.    DisplayPrompt (hwndDisplay); 
  514.  
  515.    // exit if display says to
  516.    if (dgets (hwndDisplay, szCmdLine, MAX_COMMAND_LENGTH)== -1)
  517.       break;  
  518.  
  519.    ExpandAliasString (szCmdLine, MAX_COMMAND_LENGTH);
  520.  
  521.    iInterp = InterpretCommand (hwndWinShell, hwndDisplay, szCmdLine);
  522. } while (bContinue && iInterp != -1);
  523. The first function in the loop displays the command prompt on the WStdio 
  524. window.  The next job is to obtain a line of text from the user, which is accomplished 
  525. by the dgets() macro.  Note that if dgets() returns -1, it means the user has closed the 
  526. window, and the loop must be exited.  After the user input has been obtained, the 
  527. input is passed to the ExpandAliasString() function in the ALIAS.C module, which will 
  528. expand any aliases found in the string.  Finally, the string is passed to the 
  529. InterpretCommand function in the INTERP.C module.  It is in this module that the 
  530. string is parsed and executed.
  531. Note that commands retrieved from the command line are not given a chance to 
  532. expand the marked text symbol by using the WSTDIO.C module.  The marked text 
  533. symbol is provided so that the symbol in the command string is replaced by the text 
  534. marked in the WStdio window.  Although this would be a desirable alternative, a 
  535. minor design flaw stopped me from implementing it.
  536. II.B.2 The Action Button Command Path
  537.  The ACTNBAR.C module can instigate a command by sending a message to the 
  538. WINSHELL window.  The WINSHELL responds by executing the command using the 
  539. flow of control as seen in figure 7.  The following code is executed in response to 
  540. such a message:
  541. GetWindowText (LOWORD (lParam), szCmdLine, MAX_COMMAND_LENGTH);
  542. ExpandAliasString (szCmdLine, MAX_COMMAND_LENGTH);
  543. ExpandMarkedText  (szCmdLine, MAX_COMMAND_LENGTH);
  544. InterpretCommand  (hwndWinShell, NULL, szCmdLine);
  545. As you can see, the code is very similar to that used in the command 
  546. interpretation loop in the previous section.  The only difference is that commands 
  547. executed in response to the ACTNBAR module get to use the ExapandMarkedText() 
  548. function, which expand the marked text symbol into the text currently marked on the 
  549. WStdio window.  Also, the command executed in response to the ACTNBAR module 
  550. are passed a WStdio window handle of NULL.  This means that these function will 
  551. not be able to output any data to the WStdio window.
  552. II.B.3 The ALIAS.C Module
  553. The ALIAS.C module provides aliases expansion for command strings.  It is 
  554. implemented as a Windows DLL, which provides the following advantages.  For all 
  555. instances of the Windows Shell running, they all share a common ALIAS module.  
  556. This means that if an alias changed in one shell, it is changed for all shells.  This 
  557. methods also expedites the loading process of Windows Shell, because the default 
  558. aliases only have to be read from disk once, for the first module.
  559. The implementation of the ALIAS module is quite simple.  It maintains a 
  560. dynamically resizable array of elements.  Each element contains an alias name and 
  561. an alias value.  The module provides a dialog box for adding and deleting aliases, 
  562. and the ExpandAliasString() function, which takes a string and expands any aliases 
  563. within it.
  564. II.B.4 The INTERP.C Module
  565. The third and perhaps most important module used in command interpretation is 
  566. the INTERP.C module.  This module is responsible for parsing a command line, 
  567. determining what type of command it is, and executing the command accordingly.  
  568. There are three types of commands that the module must discriminate between.
  569. The first type of command the INTERP module looks for are shell commands.  
  570. These are commands who's code is kept inside the Window Shell.  This is 
  571. accomplished by a large switch statement that checks if the requested command is 
  572. amongst those known to be external commands.  If INTERP determines that 
  573. command is a shell command, it merely has to call the function associated with the 
  574. shell command.  All shell commands are contained in the COMMANDS.C module.  
  575. These commands are so trivial they will not be discussed.
  576. The second type of command the INTERP module looks for are external 
  577. commands.  These commands are implemented as Windows DLLs.  The INTERP 
  578. function searches the default directory for files who's names match the specified 
  579. command name and ending with the .WS extension.  If a corresponding external 
  580. command file is found, the DLL is loaded and control is passed to it.  The 
  581. specifications for an external command are outline in appendix A.
  582. The third type of command the INTERP module looks for are executable files.  
  583. Windows provides the WinExec() function which performs this function.  However, 
  584. the WinExec function only searches for executable files with and extension of .EXE.   
  585. DOS on the other hand, allows a different type of executable file to end with the .COM 
  586. extension.  Also, Windows provides a DOS shell configuration file which can also be 
  587. executed, who's extension is .PIF.  In order all these types of files to be executed, 
  588. the INTERP module first gives the WinExec function a crack at executing it.  If this 
  589. fails, INTERP then searches the PATH for a file who's name matches the command 
  590. name and ends in either a .COM or a .PIF.  If either of these are found, an explicit file 
  591. name and path is created and passed to the WinExec function, which will then 
  592. execute the appropriate files.
  593. If none of the above types of commands are found to match the specified 
  594. command, an "unknown command" message is displayed.
  595.  
  596. III. DEVELOPMENT PROCESS
  597. This section discusses some of the problems and considerations that I ran into 
  598. while designing and implementing the Windows Shell.   On a general note, it seems 
  599. that many of the major design issues I originally set out to implement worked quite 
  600. well.  From the onset, I intended to create a Windows application that did not have a 
  601. message loop in WinMain function.  I wanted the main module worry more about the 
  602. matters of command interpretation than windowing.   The message loop was to be 
  603. hidden in the screen I/O functions, which is how it is now implemented.   Also, the 
  604. idea of having external commands implemented as DLLs worked out great.  I really 
  605. had no idea if either of these ideas were feasible when I started.
  606. User Feedback
  607. So far I have received feedback from on;y one person.  I received a call from a 
  608. software tester in Pennsylvania, who had downloaded the Windows Shell from a 
  609. local BBS.  He said that he really liked the product, and commented that I should 
  610. consider going shareware with the it.  Furthermore he had the following 
  611. recommendations for the Windows Shell:
  612.     -User loadable alias files, supporting multiple loads of different files
  613.     - Allow more variables to be user configurable, such as the scrollback buffer 
  614. size.
  615. Problems Encountered
  616. The remainder of this section will be organized in a problem-solution format.  I 
  617. will first present a problem or consideration, and then discuss how it was solved or 
  618. overlooked.
  619.  
  620. P -  As mentioned in section II.B.1, commands entered at the command line aren't 
  621. given a chance to expand the marked text symbol into text that is actually marked on 
  622. the WStdio window.  I had originally intended to provide this feature, but the 
  623. implementation in the WStdio window prevented it.  The problem lies in that after a 
  624. command is entered by the user, the ENTER key immediately generates a newline 
  625. character.  When a newline is output to the WStdio window, the marked text is 
  626. automatically un-marked.  Thus by the time the command is being interpreted, any 
  627. marked text is no longer valid.  The Action Bar does not have this problem because it 
  628. does not generate a newline character when pressed.
  629. S - The solution for this problem was to disallow marked text expansion on the 
  630. command line.  While this is more or less avoiding the problem, I have not found an 
  631. acceptable way to rectify it.
  632.  
  633. P - The Microsoft C functions for manipulating ENVIRONMENT variables do not work 
  634. in a Windows program.
  635. S - The solution was to get a pointer to the environment area, and do all 
  636. ENVIRONMENT manipulation functions by hand.  This was a messy job, but the only 
  637. way I found to get it to work.
  638.  
  639. P - In Windows, the ENVIRONMENT of the parent is not inherited by the programs is 
  640. spawns.  This has made the ENVIRONMENT editor almost useless.
  641. S - There is nothing that can be done for this, except to not use Windows.
  642.  
  643. P - The speed of I/O to the display was too slow.  For example, as lines were output 
  644. from an LS command, the rate at which lines were displayed was very slow.  This is 
  645. of course do to the graphical nature of displaying and scrolling text.
  646. S - The solution was to buffer the lines as they came in, and to output them in bursts.  
  647. This made the code considerably more difficult to understand, but the end result was 
  648. highly desirable.  I found that by just buffering every other line, screen I/O was 
  649. greatly increased.
  650.  
  651. P - Use of "strtok" C library function is dangerous.  Because I am lexically analyzing 
  652. a command line to determine what to execute, what flags to set, etc, I intended to use 
  653. strtok.  However, the C library version is not compatible with Windows, because it 
  654. allocates memory in an incompatible way.  So I decided I would write my own. 
  655. However, I realized that the way strtok is used will not work in a multi tasking 
  656. environment.  Strtok "remembers" the last parameter you gave it, which allows you 
  657. to call it successively to get the next tokens.  But with different programs using strtok 
  658. simultaneously, it will get garbled.  
  659. S - I considered two possible solutions for this problem.  The first was to redesign 
  660. my strtok function to always require the string to be parsed as a parameter.  The 
  661. calling routine would have to supply two buffers, one holding the source string, the 
  662. second holding a buffer in which strtok could do it's work.  This however, would be 
  663. quite cumbersome for the client using strtok.  The second solution is to carefully 
  664. organize the use of strtok so that no two modules would ever conflict.  I chose to go 
  665. with the latter, since it seems to work and required the least amount of change.
  666.  
  667. APPENDIX A. THE EXTERNAL COMMANDS DLL INTERFACE
  668.  
  669.  
  670. OVERVIEW
  671.     Each "External Command" is a DLL that contains the code for that command.  
  672. The 'GENERIC.C' and associated files in the GENERIC directory provide a template 
  673. for creating a new External Command.  
  674.     An important consideration in implementing a new command is where to store 
  675. your data.  In order for your DLL to be completely reentrant, no variable can be 
  676. stored in the data segment.  That is, don't declare variables outside of a function, 
  677. and no static variables inside a function.  The reason for this is that each invocation 
  678. of a DLL function uses that same data segment.  If a DLL function was called 
  679. reentrantly,  static variables would be overwritten.  Thus, if a DLL requires more data 
  680. than will fit on the stack, use dynamic allocation.
  681.  
  682. REQUIREMENTS
  683.  
  684. Each DLL must provide the following 3 functions for use by Windows Shell:
  685.  
  686. int FAR PASCAL ModuleProc (HWND hwndDisplay, int argc, LPSTR argv[]);
  687. @ ORDINAL 3
  688. hwndDisplay    - Window handle of STDIO Display to use for I/O.
  689. argc    - Number of command line arguments.
  690. argv    - Array of pointers to command line arguments.  The first pointer 
  691. always points to the name of the DLL.
  692. This function is called to let the DLL do the function which it is providing.  For 
  693. example, if this were a DLL providing a file deletion function, the DLL would perform 
  694. the deletion at this time.
  695.  
  696. int FAR PASCAL ShowOptions (HWND hwndParent);
  697. @ ORDINAL 4
  698. hwndDisplay    - Window handle of STDIO Display to use for I/O or as parent.
  699. This function is called to tell the DLL to show it's options box.  The DLL should 
  700. display a window which allows the user to set options in the DLL.
  701.  
  702. int FAR PASCAL ShowAbout (HWND hwndParent);
  703. @ ORDINAL 5
  704. hwndDisplay    - Window handle of STDIO Display to use for I/O or as parent.
  705. This function is called to tell the DLL to show it's about box.  The DLL should display 
  706. an about window at this time.
  707.  
  708. NOTE - It is essential that the DLL export these functions at the specified ordinal 
  709. value in it's .DEF file.  Otherwise, The Windows Shell will not properly access the 
  710. DLL.
  711.  
  712.  
  713. USING THE DISPLAY
  714. The header file 'wstdio.h' has been provided for outputing lines and other function to 
  715. the display.  The most common of these is dputs(), which you can use to output a line 
  716. to the display.  See the header file for the description of the rest of the functions.
  717.  
  718. UTILITY FUNCTIONS
  719. The 'wslib.dll' provides several useful functions for parsing command lines, and 
  720. yielding to other applications.  It is extremely important that you use the 
  721. YieldToOthers() function your code sits in a tight loop for an extended length of time.  
  722. See the header file 'wslib.h' for a list of useful functions.
  723.  
  724. Mark Krieg
  725. 931 South Russel Street
  726. York, Pennsylvania 17402
  727.  
  728. v
  729.  
  730. 25
  731.  
  732.  
  733.